#pragma once
// 实现任意类型封装

#include <iostream>
#include<assert.h>

class Any
{
private:
    // 内置一个模版类型
    class placeholder
    {
    public:
        virtual ~placeholder() {}

        virtual const std::type_info &type() = 0;
        virtual placeholder *clone() = 0;
    };

    template <typename T>

    class holder : public placeholder
    {
    public:
        holder(const T &v) : val(v) {}
        ~holder() {}
        const std::type_info &type()
        {
            return typeid(T);
        }

        placeholder *clone()
        {
            return new holder(val);
        }
        T val;
    };

    placeholder *_content;

public:
    Any() : _content(NULL) {}

    template <typename T>

    Any(const T &val) : _content(new holder<T>(val))
    {
    }

    // 只要是初始化过的Any指针的真正指向的类型都是holder
    Any(const Any &other) : _content(other._content ? other._content->clone() : NULL) {}

    ~Any()
    {
        if (_content)
            delete _content;
    }

    const std::type_info &type()
    {
        return _content ? _content->type() : typeid(void);
    }

    Any &swpa(Any &other)
    {
        std::swap(_content, other._content);
        return *this;
    }


    //使用get时必须加上相应的类型
    template <typename T>

    T *get()
    {
        assert(typeid(T) == _content->type());

        return &((holder<T> *)_content)->val;
    }

    template <typename T>

    Any &operator=(const T &val)
    {
        // 为val创建一个临时对象，然后进行交换，这样在临时对象被销毁时，会将原先保存的placeholder进行销毁
        Any(val).swpa(*this);
        return *this;
    }

    Any &operator=(Any other)
    {
        other.swpa(*this);
        return *this;
    }
};
